package com.yellowninja.backup.model;

import com.yellowninja.backup.util.Backup;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.Date;
import java.util.Calendar;

import javax.swing.table.AbstractTableModel;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;

public class BackupTableModel extends AbstractTableModel {
	static final long serialVersionUID = 1L;

	private SimpleDateFormat format;

	private String[] columnNames = { "Name", "Last Run", "Save Location" };

	private XMLConfiguration config;

	/**
	 * Constructs a new binding table model collection.
	 */
	public BackupTableModel(XMLConfiguration config) {
		this.config = config;
		this.format = new SimpleDateFormat("MMddyyyy");
	}

	/**
	 * Returns the number of columns in this model.
	 * 
	 * @return The number of columns in this model.
	 */
	public int getColumnCount() {
		return columnNames.length;
	}

	/**
	 * Returns the number of rows currently in this model.
	 * 
	 * @return The number of rows currently in this model.
	 */
	public int getRowCount() {
		return config.getStringArray("backups.backup.name").length;
	}

	/**
	 * Returns the column name for the given column number.
	 * 
	 * @param col
	 *            The column number to select.
	 * @return The name of the column.
	 */
	public String getColumnName(int col) {
		return columnNames[col];
	}

	public boolean isCellEditable(int row, int column) {
		return (column != 0);
	}

	/**
	 * Gets the cell value for the given row and column.
	 * 
	 * @param row
	 *            The row of the value.
	 * @param col
	 *            The column of the value.
	 * @return The value in the given cell.
	 */
	public Object getValueAt(int row, int col) {
		switch (col) {
		case 0:
			return config.getString("backups.backup(" + row + ").name");
		case 1:
			Calendar lastRun = parseTimestamp(config
					.getString("backups.backup(" + row + ").lastRun"));
			if (lastRun != null)
				return lastRun.getTime();
			else
				return null;
		case 2:
			return config.getString("backups.backup(" + row + ").saveLocation");
		}
		return null;
	}

	/**
	 * Sets the cell value for the given row and column.
	 */
	public void setValueAt(Object value, int row, int col) {
		switch (col) {
		case 0:
			config.setProperty("backups.backup(" + row + ").name",
					(String) value);
			fireTableCellUpdated(row, col);
			break;
		case 1:
			config.setProperty("backups.backup(" + row + ").lastRun", format
					.format((Date) value));
			fireTableCellUpdated(row, col);
			break;
		case 2:
			config.setProperty("backups.backup(" + row + ").saveLocation",
					(String) value);
			fireTableCellUpdated(row, col);
			break;
		}
	}

	/**
	 * Gets the class type for the given column number.
	 * 
	 * @param col
	 *            The column number to get.
	 * @return The class type of the given column.
	 */
	public Class<?> getColumnClass(int col) {
		switch (col) {
		case 0:
			return String.class;
		case 1:
			return Date.class;
		case 2:
			return String.class;
		}

		return null;
	}

	public Backup getBackup(int row) {
		Calendar lastRun = parseTimestamp(config.getString("backups.backup("
				+ row + ").lastRun"));
		Backup backup = null;
		if (lastRun == null)
			backup = new Backup(row, config.getString("backups.backup(" + row
					+ ").name"), config.getString("backups.backup(" + row
					+ ").backupLocation"), config.getString("backups.backup("
					+ row + ").saveLocation"), new Integer(config
					.getString("backups.backup(" + row + ").type")),
					new Integer(config.getString("backups.backup(" + row
							+ ").schedule")));
		else
			backup = new Backup(row, config.getString("backups.backup(" + row
					+ ").name"), config.getString("backups.backup(" + row
					+ ").backupLocation"), config.getString("backups.backup("
					+ row + ").saveLocation"), lastRun.getTime(), new Integer(
					config.getString("backups.backup(" + row + ").type")),
					new Integer(config.getString("backups.backup(" + row
							+ ").schedule")));

		return backup;
	}

	public synchronized boolean updateRow(Backup backup) {
		int row = backup.getID();
		if (row != -1) {
			config.setProperty("backups.backup(" + row + ").name", backup
					.getName());
			config.setProperty("backups.backup(" + row + ").backupLocation",
					backup.getBackupLocation());
			config.setProperty("backups.backup(" + row + ").saveLocation",
					backup.getSaveLocation());
			config.setProperty("backups.backup(" + row + ").type", ""
					+ backup.getType());
			config.setProperty("backups.backup(" + row + ").schedule", ""
					+ backup.getSchedule());
			if (backup.getLastRunDate() != null)
				config.setProperty("backups.backup(" + row + ").lastRun",
						format.format(backup.getLastRunDate()));
			fireTableRowsUpdated(row, row);
			return true;
		}

		return false;
	}

	public synchronized boolean removeRow(int row) {
		config.clearTree("backups.backup(" + row + ")");
		fireTableRowsDeleted(row, row);
		return true;
	}

	public synchronized void addRow(Backup backup) {
		int row = config.getStringArray("backups.backup.name").length;
		config
				.addProperty("backups.backup(" + row + ").name", backup
						.getName());
		config.addProperty("backups.backup(" + row + ").backupLocation", backup
				.getBackupLocation());
		config.addProperty("backups.backup(" + row + ").saveLocation", backup
				.getSaveLocation());
		config.addProperty("backups.backup(" + row + ").type", ""
				+ backup.getType());
		config.addProperty("backups.backup(" + row + ").schedule", ""
				+ backup.getSchedule());
		if (backup.getLastRunDate() != null)
			config.addProperty("backups.backup(" + row + ").lastRun", format
					.format(backup.getLastRunDate()));
		fireTableRowsInserted(row, row);
	}

	public synchronized void saveModel() throws ConfigurationException {
		config.save();
	}

	public String[] getBackupNames() {
		return config.getStringArray("backups.backup.name");
	}

	private Calendar parseTimestamp(String timestamp) {
		if (timestamp != null) {
			try {
				Date d = format.parse(timestamp);
				Calendar cal = Calendar.getInstance();
				cal.setTime(d);
				return cal;
			} catch (ParseException pe) {
				System.err.println(pe.getLocalizedMessage());
				pe.printStackTrace();
			}
		}

		return null;
	}

}
